home *** CD-ROM | disk | FTP | other *** search
/ Alles Voor Internet / Tout Pour Internet / alles voor internet.iso / MacInternet™ / Unix / mcvert2.15.shar / unpack.c < prev   
Encoding:
C/C++ Source or Header  |  1993-11-25  |  6.7 KB  |  246 lines

  1. #include "mactypes.h"
  2.  
  3. extern word magic[];
  4. extern char *dir, *ext;
  5. extern int info_only;
  6.  
  7. ulong pit_datalen, pit_rsrclen;
  8. word hqx_crc, write_pit_fork();
  9. char pitfname[SYSNAMELEN];    /* name of file being unpacked */
  10. FILE *pitfile;            /* output file */
  11.  
  12. branch branchlist[255], *branchptr, *read_tree();
  13. leaf leaflist[256], *leafptr;
  14. word Huff_nibble, Huff_bit_count;
  15.  
  16. byte(*read_char) (), get_crc_byte(), getHuffbyte();
  17.  
  18. word 
  19. un_pit()
  20. {
  21.     char PitId[4];
  22.     int i;
  23.     word pit_crc;
  24.  
  25.     hqx_crc = 0;
  26.     /* Read and unpack until the PackIt End message is read */
  27.     for (;;) {
  28.         read_char = get_crc_byte;
  29.         for (i = 0; i < 4; i++)
  30.             PitId[i] = (char) get_crc_byte();
  31.         if (!strncmp(PitId, "PEnd", 4))
  32.             break;
  33.  
  34.         if (strncmp(PitId, "PMag", 4) && strncmp(PitId, "PMa4", 4))
  35.             error("Unrecognized Packit format message %s", PitId);
  36.  
  37.         if (PitId[3] == '4') {
  38.             /* if this file is compressed */
  39.             /* read the Huffman decoding  */
  40.             /* tree that is on the input  */
  41.             /* and use Huffman decoding   */
  42.             /* subsequently               */
  43.             branchptr = branchlist;
  44.             leafptr = leaflist;
  45.             Huff_bit_count = 0;
  46.             (void)read_tree();
  47.             read_char = getHuffbyte;
  48.         }
  49.         read_pit_hdr();               /* also calculates datalen,
  50.                             * rsrclen, pitfile, pitfname */
  51.         pit_crc = write_pit_fork(pit_datalen, (ulong)0);
  52.         pit_crc = write_pit_fork(pit_rsrclen, (ulong)pit_crc);
  53.         check_pit_crc(pit_crc, "  File data/rsrc CRC mismatch in %s", pitfname);
  54.         mclose(&pitfile, "pitfile");
  55.     }
  56.     hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
  57.     hqx_crc = (hqx_crc << 8) ^ magic[hqx_crc >> 8];
  58.     return hqx_crc;
  59. }
  60.  
  61. check_pit_crc(calc_crc, msg, name)
  62.     word calc_crc;
  63.     char msg[], name[];
  64.  
  65. {
  66.     word read_crc;
  67.  
  68.     read_crc = (*read_char) () << 8;
  69.     read_crc |= (*read_char) ();
  70.     if (read_crc != calc_crc)
  71.         error(msg, name);
  72. }
  73.  
  74. /*  
  75.  * This routine reads the header of a packed file and appropriately
  76.  * twiddles it, determines if it has CRC problems, creates the .bin
  77.  * file, and puts the info into the .bin file.  Output is
  78.  * pit_datalen, pit_rsrclen, pitfname, pitfile
  79.  */
  80. read_pit_hdr()
  81. {
  82.     register int n;
  83.     register byte *pit_byte;
  84.     register ulong pit_crc;
  85.     pit_header pit;
  86.     info_header info;
  87.     short crc;
  88.     char *action;
  89.     long len;
  90.  
  91.     extern short calc_mb_crc();
  92.  
  93.     /* read the pit header and compute the CRC */
  94.     pit_crc = 0;
  95.     pit_byte = (byte *) & pit;
  96.     for (n = 0; n < sizeof(pit_header); n++) {
  97.         *pit_byte = (*read_char) ();
  98.         pit_crc = ((pit_crc & 0xff) << 8)
  99.             ^ magic[*pit_byte++ ^ (pit_crc >> 8)];
  100.     }
  101.  
  102.     /* stuff the pit header data into the info header */
  103.     bzero((char*)&info, sizeof(info_header));
  104.     info.nlen = pit.nlen;
  105.     if (pit.nlen > sizeof(info.name))
  106.         error("Error: corrupt PIT data format", "");
  107.     /*
  108.      * expect a valid Macintosh file name since it came from a PIT file
  109.      * and don't potentially corrupt a valid copied name via macify
  110.      */
  111.     strncpy((char*)info.name, (char*)pit.name, (int)pit.nlen);/* name */
  112.     bcopy((char*)pit.type, (char*)info.type, 9);  /* type, author, flag */
  113.     bcopy((char*)pit.dlen, (char*)info.dlen, 16); /* (d,r)len, (c,m)tim */
  114.     info.flags &= 0x7e;               /* reset lock bit, init bit */
  115.     if (pit.protect & 0x40)
  116.         info.protect = 1;           /* copy protect bit */
  117.     info.uploadvers = '\201';
  118.     info.readvers = '\201';
  119.  
  120.     /* calculate MacBinary CRC */
  121.     crc = calc_mb_crc((unsigned char*)&info, 124L, 0);
  122.     info.crc[0] = (char) (crc >> 8);
  123.     info.crc[1] = (char) crc;
  124.  
  125.     /* Create the .bin file and write the info to it */
  126.     pit.name[pit.nlen] = '\0';
  127.     unixify((char*)pit.name);
  128.  
  129.     len = strlen(dir) + strlen((char*)pit.name) + strlen(ext) + 1;
  130.     if (len >= sizeof(pitfname))
  131.         error("Error: generated pitfname would be too long", "");
  132.     sprintf(pitfname, "%s/%s%s", dir, pit.name, ext);
  133.  
  134.     if (info_only)
  135.         action = (read_char == get_crc_byte) ? "Packed" : "Compressed";
  136.     else
  137.         action = (read_char == get_crc_byte) ? "Unpacking" : "Decompressing";
  138.  
  139.     fprintf(convert, " %-14s%-30s type = \"%4.4s\", author = \"%4.4s\"\n",
  140.         action, pit.name, pit.type, pit.auth);
  141.     fflush(convert);
  142.     print_bin_hdr("Creating", &info);
  143.     pitfile = mopen(pitfname, "", "w");
  144.     check_pit_crc((word)pit_crc, "  File header CRC mismatch in %s", pitfname);
  145.     if (1 != fwrite((char*)&info, sizeof(info_header), 1, pitfile))
  146.         error("fwrite failed on pitfile", "");
  147.  
  148.     /* Get a couple of items we'll need later */
  149.     bcopy((char*)pit.dlen, (char*)&pit_datalen, 4);
  150.     pit_datalen = mac2long(pit_datalen);
  151.     bcopy((char*)pit.rlen, (char*)&pit_rsrclen, 4);
  152.     pit_rsrclen = mac2long(pit_rsrclen);
  153. }
  154.  
  155. /* This routine copies bytes from the decoded input stream to the output
  156.     and calculates the CRC.  It also pads to a multiple of 128 bytes on the
  157.     output, which is part of the .bin format */
  158. word 
  159. write_pit_fork(nbytes, calc_crc)
  160.     register ulong nbytes;
  161.     register ulong calc_crc;
  162. {
  163.     register ulong b;
  164.     int extra_bytes;
  165.  
  166.     /* pad fork to mult of * 128 bytes */
  167.     extra_bytes = 127 - (nbytes + 127) % 128;
  168.     while (nbytes--) {
  169.         b = (*read_char) ();
  170.         calc_crc = ((calc_crc & 0xff) << 8) ^ magic[b ^ (calc_crc >> 8)];
  171.         if (EOF == putc((char)b, pitfile))
  172.             error("Error: putc failed on pitfile", "");
  173.     }
  174.     while (extra_bytes--)
  175.         if (EOF == putc(0, pitfile))
  176.             error("Error: putc failed on pitfile", "");
  177.     return (word) calc_crc;
  178. }
  179.  
  180. /* This routine recursively reads the compression decoding data.
  181.    It appears to be Huffman compression.  Every leaf is represented
  182.    by a 1 bit, then the byte it represents.  A branch is represented
  183.    by a 0 bit, then its zero and one sons */
  184. branch *
  185. read_tree()
  186. {
  187.     register branch *branchp;
  188.     register leaf *leafp;
  189.     register ulong b;
  190.  
  191.     if (!Huff_bit_count--) {
  192.         Huff_nibble = get_crc_byte();
  193.         Huff_bit_count = 7;
  194.     }
  195.     if ((Huff_nibble <<= 1) & 0x0100) {
  196.         leafp = leafptr++;
  197.         leafp->flag = 1;
  198.         b = get_crc_byte();
  199.         leafp->data = Huff_nibble | (b >> Huff_bit_count);
  200.         Huff_nibble = b << (8 - Huff_bit_count);
  201.         return (branch *) leafp;
  202.     } else {
  203.         branchp = branchptr++;
  204.         branchp->flag = 0;
  205.         branchp->zero = read_tree();
  206.         branchp->one = read_tree();
  207.         return branchp;
  208.     }
  209. }
  210.  
  211. /* This routine returns the next 8 bits.  It finds the byte in the
  212.    Huffman decoding tree based on the bits from the input stream. */
  213. byte 
  214. getHuffbyte()
  215. {
  216.     register branch *branchp;
  217.  
  218.     branchp = branchlist;
  219.     while (!branchp->flag) {
  220.         if (!Huff_bit_count--) {
  221.             Huff_nibble = get_crc_byte();
  222.             Huff_bit_count = 7;
  223.         }
  224.         branchp = ((Huff_nibble <<= 1) & 0x0100) ? branchp->one : branchp->zero;
  225.     }
  226.     return ((leaf *) branchp)->data;
  227. }
  228.  
  229. /* This routine returns the next byte on the .hqx input stream, hiding
  230.     most file system details at a lower level.  .hqx CRC is maintained
  231.     here */
  232. byte 
  233. get_crc_byte()
  234. {
  235.     register ulong c;
  236.     extern byte *buf_ptr, *buf_end;
  237.  
  238.     if (buf_ptr == buf_end) {
  239.         if (fill_hqxbuf(0) == 0)
  240.             error("premature EOF reading PIT info from BinHex 4.0 file", "");
  241.     }
  242.     c = *buf_ptr++;
  243.     hqx_crc = ((hqx_crc << 8) | c) ^ magic[hqx_crc >> 8];
  244.     return (byte) c;
  245. }
  246.